home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / radiance / simplerd.lha / simplerad / FinalFTP / Prims / mprims.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-26  |  24.0 KB  |  787 lines

  1. /**********************************************************************/
  2. /* mprims.c :                                                         */
  3. /*                                                                    */
  4. /* Mesh some basic primtives into an initial mesh of 4-vertex         */
  5. /* polygons with associated normals                                   */
  6. /*                                                                    */
  7. /* Primitives supported same as those in QuickModel program. Output   */
  8. /* is a set of patches                                                */
  9. /*                                                                    */
  10. /* - Quickmodel primitives support: cones, cubes, cylinders, spheres  */
  11. /* - Option of normals facing in or out                               */
  12. /*                                                                    */
  13. /* Copyright (C) 1992, Bernard Kwok                                   */
  14. /* All rights reserved.                                               */
  15. /* Revision 1.0                                                       */
  16. /* May, 1992                                                          */
  17. /**********************************************************************/
  18. #include <stdio.h>
  19. #include <math.h>
  20. #include "mprims.h"
  21.  
  22. /**********************************************************************/
  23. /* Print a polygonal patch out */
  24. /**********************************************************************/
  25. void print_polygon(p, num)
  26.      Polygon *p;
  27.      int num;
  28. {
  29.   int i;
  30.  
  31.   /* Print normal */
  32.   printf("Patch norm%d %d {",num, p->size);
  33.   for(i=0;i<p->size;i++) {
  34.     if (normal_direction == NORMAL_OUT) 
  35.       printf(" { %g %g %g }", p->normal[i].x, p->normal[i].y, 
  36.          p->normal[i].z);
  37.     else
  38.       printf(" { %g %g %g }", -p->normal[i].x, -p->normal[i].y, 
  39.          -p->normal[i].z);
  40.   }
  41.   printf(" }\n");
  42.  
  43.   /* Print vertex */
  44.   printf("Patch vert%d %d {",num, p->size);     
  45.   for(i=0;i<p->size;i++)
  46.     printf(" { %g %g %g }", p->vertex[i].x, p->vertex[i].y, 
  47.        p->vertex[i].z);
  48.   printf(" }\n");
  49. }
  50.     
  51.  
  52. /*====================================================================*/
  53. /* Cube */
  54. /*====================================================================*/
  55. double faces[6][4][3] = { /* [face][vertex][x/y/z] */
  56.   {{ -1, 1, -1}, {1, 1, -1,}, {1, 1, 1}, {-1, 1, 1}},    /* Face 0 */
  57.   {{ 1, 1, -1,}, {1, -1, -1}, {1, -1, 1}, {1, 1, 1}},    /* Face 1 */
  58.   {{ -1, -1, -1}, {-1, 1, -1}, {-1, 1, 1}, {-1, -1, 1}}, /* Face 2 */
  59.   {{ -1, 1, 1}, {1, 1, 1}, {1, -1, 1}, {-1, -1, 1}},     /* Face 3 */
  60.   {{ -1, 1, -1}, {1, 1, -1}, {1, -1, -1,}, {-1, -1, -1}},/* Face 4 */
  61.   {{ 1,-1, -1 }, {-1, -1, -1 }, {-1, -1, 1}, {1, -1, 1}} /* Face 5 */
  62. };
  63. void mesh_cube();
  64. void print_cube();
  65.  
  66. /**********************************************************************/
  67. /* Mesh a cube */
  68. /**********************************************************************/
  69. void mesh_cube(cube, du, dv, id, sid)
  70.      MCube *cube;
  71.      int id, du, dv;
  72.      char *sid;
  73. {
  74.   int i,j,k;
  75.   CPolygon *pptr;
  76.   int u,v,w;
  77.   float face_normal[3]; 
  78.   float tempv[2];
  79.  
  80.   /* Set u and v subdivision and id */
  81.   cube->du = du; cube->dv = dv;
  82.   cube->id = id; cube->sid = sid;
  83.   cube->num_polys = du * dv;
  84.  
  85.   /* Create space for du*dv patches per each of 6 faces */
  86.   for(i=0;i<6;i++) 
  87.     if ((cube->faces[i] = (CPolygon *) malloc( (du*dv) *sizeof(CPolygon)))
  88.     == NIL) { 
  89.       fprintf(stderr,"No more memory left for malloc\n");
  90.       exit(-1);
  91.     }
  92.   
  93.   for (i=0;i<6;i++) {
  94.     pptr = cube->faces[i];
  95.     
  96.     /* Set face normals and direction of normals {w=0=x, w=1=y, w=2=z} */
  97.     /* (normals facting in */
  98.     face_normal[0] = 0; face_normal[1] = 0; face_normal[2] = 0;
  99.     switch(i) {
  100.     case 0 : face_normal[Y] = 1; w = Y; u=X; v=Z; break;
  101.     case 1 : face_normal[X] = 1; w = X; u=Y; v=Z; break;
  102.     case 2 : face_normal[X] = -1; w = X; u=Y; v=Z; break;
  103.     case 3 : face_normal[Z] = 1; w = Z; u=X; v=Y; break;
  104.     case 4 : face_normal[Z] = -1; w = Z; u=X; v=Y; break;
  105.     case 5 : face_normal[Y] = -1; w = Y; u=X; v=Z; break;
  106.     default: break;
  107.     }  
  108.     
  109.     dv = cube->dv;
  110.     du = cube->du; 
  111.     if (faces[i][0][v] > faces[i][3][v]) dv = -dv;
  112.     if (faces[i][0][u] > faces[i][1][u]) du = -du; 
  113.     
  114.     /* Subdivide along 2 directions (u,v) of plane of face */
  115.     for(j=0;j < _ABS(dv);j++) {
  116.       tempv[0] = faces[i][0][v] + (2.0*j/dv);
  117.       tempv[1] = faces[i][0][v] + (2.0*(j+1)/dv);
  118.       
  119.       for(k=0;k < _ABS(du);k++) {
  120.     /* Set u,v,w coords of vertices of patch */
  121.     pptr->vertex[0][u] = pptr->vertex[3][u] = faces[i][0][u]+(2.0*k/du);
  122.     pptr->vertex[2][u] = pptr->vertex[1][u] = 
  123.       faces[i][0][u]+(2.0*(k+1)/du);
  124.  
  125.     pptr->vertex[0][v] = pptr->vertex[1][v] = tempv[0];
  126.     pptr->vertex[3][v] = pptr->vertex[2][v] = tempv[1];
  127.     
  128.     pptr->vertex[0][w] = pptr->vertex[1][w] = pptr->vertex[2][w] 
  129.       = pptr->vertex[3][w] = faces[i][0][w];
  130.     
  131.     /* Set vertex normals */
  132.     pptr->normal[0][u] = pptr->normal[1][u] = pptr->normal[2][u] = 
  133.       pptr->normal[3][u] = pptr->normal[0][v] = pptr->normal[1][v] = 
  134.         pptr->normal[2][v] = pptr->normal[3][v] = 0.0;
  135.     pptr->normal[0][w] = pptr->normal[1][w] = pptr->normal[2][w] = 
  136.       pptr->normal[3][w] = face_normal[w];
  137.     
  138.     /* Goto next patch. */
  139.     pptr++;
  140.       }
  141.     }
  142.   }
  143. }
  144.  
  145. /**********************************************************************/
  146. /* Output mesh for a unit cube */
  147. /**********************************************************************/
  148. void print_cube(cube)
  149.      MCube *cube;
  150. {
  151.   int i,j, k;
  152.   CPolygon *p;
  153.   int npatches;
  154.  
  155.   npatches = cube->du * cube->dv;
  156.  
  157.   printf("NumMeshes %d\n", 6);
  158.   /* Print mesh for each face of cube */
  159.   for (i=0;i<6;i++) {
  160.     p = cube->faces[i];
  161.     printf("Mesh mesh%s%d %d {\n", cube->sid, i, npatches);
  162.  
  163.     /* Print normals for each patch in face i */
  164.     for (j=0;j<(cube->num_polys);j++) {
  165.       printf("Patch norm%d %d {", j+1, 4);
  166.       for(k=0;k<4;k++) {
  167.     if (normal_direction == NORMAL_OUT)
  168.       printf(" { %g %g %g }", p->normal[k][0],
  169.          p->normal[k][1], p->normal[k][2]);
  170.     else
  171.       printf(" { %g %g %g }", -p->normal[k][0],
  172.          -p->normal[k][1], -p->normal[k][2]);
  173.       }
  174.       printf(" }\n");
  175.  
  176.     /* Print vertices for each patch in face i */
  177.       printf("Patch vert%d %d {", j+1, 4);
  178.       for(k=0;k<4;k++) printf(" { %g %g %g }", p->vertex[k][0],
  179.                   p->vertex[k][1], p->vertex[k][2]);
  180.       printf(" }\n");
  181.       p++;
  182.     }
  183.  
  184.     printf("}\n");
  185.   }
  186. }
  187.  
  188. /*====================================================================*/
  189. /* Sphere */
  190. /*====================================================================*/
  191. void mesh_sphere();
  192. void print_sphere();
  193.  
  194. double *sine, *cosine;
  195. /**********************************************************************/
  196. /* Calculate meshed sphere, and output */
  197. /**********************************************************************/
  198. void mesh_sphere(sphere, r, num_sub, centre, id, sid)
  199.      MSphere *sphere;
  200.      double r;
  201.      Vector centre;
  202.      int num_sub, id;
  203.      char *sid;
  204. {
  205.   register int i;
  206.   register int longitude, latitude, size, latP1, longP1;
  207.   Polygon *p;
  208.   
  209.   /* Store id, radius, centre, and # subdivisions */
  210.   sphere->num_sub = num_sub;
  211.   sphere->num_polys = 0;
  212.   sphere->r = r;
  213.   sphere->centre.x = centre.x; sphere->centre.y = centre.y; 
  214.   sphere->centre.z = centre.z;
  215.   sphere->id = id; sphere->sid = sid;
  216.  
  217.   /* Set sphere subdivision */
  218.   if (sine != NIL) free((char *) sine);  
  219.   if ((sine = (double *) malloc((num_sub + 1) * 4 * (sizeof(double))))
  220.       == NIL){ 
  221.     fprintf(stderr,"No more memory left for malloc\n");
  222.     exit(-1);
  223.   }
  224.   cosine = sine + 2 * (num_sub + 1);
  225.   for (i = 0; i < 2 * num_sub; i++) {
  226.     sine[i] = sin(M_PI / num_sub * i);
  227.     cosine[i] = cos(M_PI / num_sub * i);
  228.   }
  229.   sine[num_sub] = 0.;
  230.   cosine[num_sub] = -1.;
  231.   sine[2 * num_sub] = 0.;
  232.   cosine[2 * num_sub] = 1.;
  233.  
  234.   /* Calculate vertices and normals */
  235.   if ((p = sphere->poly = 
  236.     (Polygon *) malloc(2 * num_sub * num_sub * sizeof(Polygon))) == NIL) {
  237.     fprintf(stderr,"No more memory left for malloc\n");
  238.     exit(-1);
  239.   }
  240.   for (longitude = 0; longitude < 2 * num_sub; longitude++) {
  241.     longP1 = longitude + 1;
  242.     for (latitude = 0; latitude < num_sub; latitude++) {
  243.       size = 0;
  244.       latP1 = latitude + 1;
  245.       sphere->num_polys++;
  246.  
  247.       /* Calculate normals */
  248.       p->normal[size].x = sine[latitude] * cosine[longitude];
  249.       p->normal[size].y = sine[latitude] * sine[longitude];
  250.       p->normal[size].z = cosine[latitude];
  251.       size++;
  252.  
  253.       p->normal[size].x = sine[latP1] * cosine[longitude];
  254.       p->normal[size].y = sine[latP1] * sine[longitude];
  255.       p->normal[size].z = cosine[latP1];
  256.       size++;
  257.  
  258.       if (latitude < num_sub - 1) {
  259.     p->normal[size].x = sine[latP1] * cosine[longP1];
  260.     p->normal[size].y = sine[latP1] * sine[longP1];
  261.     p->normal[size].z = cosine[latP1];
  262.     size++;
  263.       }
  264.       if (latitude != 0) {
  265.     p->normal[size].x = sine[latitude] * cosine[longP1];
  266.     p->normal[size].y = sine[latitude] * sine[longP1];
  267.     p->normal[size].z = cosine[latitude];
  268.     size++;
  269.       }
  270.       
  271.       /* Keep track of number of vertices */
  272.       p->size = size;
  273.  
  274.       /* Calculate vertices */
  275.       for (i = 0; i < size; i++) {
  276.     p->vertex[i].x = 
  277.       p->normal[i].x * r + centre.x;
  278.     p->vertex[i].y = 
  279.       p->normal[i].y * r + centre.y;
  280.     p->vertex[i].z = 
  281.       p->normal[i].z * r + centre.z;
  282.       }
  283.       p++;
  284.     }
  285.   }
  286. }
  287.  
  288. /**********************************************************************/
  289. /* Output sphere patch */
  290. /**********************************************************************/
  291. void print_sphere(sphere)
  292.      MSphere *sphere;
  293. {
  294.   int i,j;
  295.   Polygon *p;
  296.  
  297.   p = sphere->poly;
  298.  
  299.   printf("NumMeshes %d\n", 1);  
  300.   printf("Mesh mesh%s%d %d {\n", sphere->sid, 1, sphere->num_polys);
  301.  
  302.   for(i=0;i<(sphere->num_polys);i++) {
  303.     
  304.     printf("Patch norm%d %d{",i+1, p->size);
  305.     for(j=0;j<(p->size);j++) {
  306.       if (normal_direction == NORMAL_OUT)
  307.     printf(" { %g %g %g }", p->normal[j].x, 
  308.            p->normal[j].y, p->normal[j].z);
  309.       else
  310.     printf(" { %g %g %g }", -p->normal[j].x, 
  311.            -p->normal[j].y, -p->normal[j].z);
  312.     }
  313.     printf(" }\n");
  314.     
  315.     printf("Patch vert%d %d{", i+1, p->size);
  316.     for(j=0;j<(p->size);j++) 
  317.       printf(" { %g %g %g }", p->vertex[j].x, p->vertex[j].y, 
  318.          p->vertex[j].z);
  319.     printf(" }\n");
  320.     p++;
  321.   }
  322.   printf("}\n");
  323. }
  324.  
  325. /*====================================================================*/
  326. /* Cone */
  327. /*====================================================================*/
  328. double Unit();
  329. Vector cNormal();
  330. void mesh_cone();
  331.  
  332. /**********************************************************************/
  333. #define MIN_LENGTH 1.e-7
  334. double Unit(vp)
  335.      register Vector *vp;
  336. {
  337.   double length, temp;
  338.     
  339.   temp= vp->x*vp->x + vp->y*vp->y + vp->z*vp->z;
  340.   if(temp <= MIN_LENGTH)
  341.     return(-1.);
  342.   length= sqrt(temp);
  343.   vp->x /= length;
  344.   vp->y /= length;
  345.   vp->z /= length;
  346.   return(length);
  347. }
  348.  
  349. /**********************************************************************/
  350. /* Vector cross product                                               */
  351. /**********************************************************************/
  352. Vector Cross(a,b)
  353.     Vector a,b;
  354. {
  355.   Vector c;
  356.   
  357.   c.x= a.y*b.z - a.z*b.y;
  358.   c.y= a.z*b.x - a.x*b.z;
  359.   c.z= a.x*b.y - a.y*b.x;
  360.   return(c);
  361. }
  362.  
  363. /**********************************************************************/
  364. /* Find normal along circle of cone */
  365. /**********************************************************************/
  366. Vector cNormal(v1, base, top)
  367.      Vector v1, base, top;
  368. {
  369.   Vector v2, v3, result;
  370.   
  371.   v2.x= top.x-base.x;
  372.   v2.y= top.y-base.y;
  373.   v2.z= top.z-base.z;
  374.   
  375.   v3= Cross(v2, v1);
  376.   result= Cross(v3, v2);
  377.   if(Unit(&result) < 0.) {
  378.     fprintf(stderr, "couldn't normalize vector\n");
  379.     exit(1);
  380.   }
  381.   return(result);
  382. }
  383.  
  384. /**********************************************************************/
  385. /* Create meshed cone */
  386. /**********************************************************************/
  387. void mesh_cone(cone, rb, rt, h, n1, n2, id, sid)
  388.      MCone *cone;
  389.      double rb, rt, h; /* radiuse of base and top, and height */
  390.      int n1, n2; /* subdivision for base and sides resp. */
  391.      int id; 
  392.      char *sid;
  393. {
  394.   double angle, s1, s2, u1, u2;
  395.   int i, j, k, ii;
  396.   Vector base, top, *circle, *normal, cNormal();
  397.   Polygon *bp, *tp;
  398.  
  399.   if(rb <= 0. || rb > 100. || rt <= 0. || rt > 100. || h <= 0. || h > 100.
  400.      || n1 < 4 || n1 > 100 || n2 < 4 || n2 > 100) 
  401.     fprintf(stderr, "Sorry, args out of range\n");
  402.   
  403.   cone->rb = rb;
  404.   cone->rt = rt;
  405.   cone->h = h;
  406.   cone->num_side_polys = n1 * n2;
  407.   cone->num_disc_polys = n2;
  408.   cone->id = id;
  409.   cone->sid = sid;
  410.  
  411.   if ((bp = cone->bpoly = (Polygon *) malloc( n1 * sizeof(Polygon) )) == NIL) {
  412.     fprintf(stderr,"No more memory left for malloc\n");
  413.     exit(-1);
  414.   }
  415.   if ((tp = cone->tpoly = (Polygon *) malloc( n1 * sizeof(Polygon) )) == NIL) {
  416.     fprintf(stderr,"No more memory left for malloc\n");
  417.     exit(-1);
  418.   }
  419.   
  420.   if ((circle = (Vector *) malloc(n1*sizeof(Vector))) == NIL) {
  421.     fprintf(stderr,"No more memory left for malloc\n");
  422.     exit(-1);
  423.   }
  424.   if ((normal= (Vector *) malloc(n1*sizeof(Vector))) == NIL) {
  425.     fprintf(stderr,"No more memory left for malloc\n");
  426.     exit(-1);
  427.   }
  428.   
  429.   /* Calculate base and top circular points and normals */
  430.   for(i=0;i<n1;i++) {
  431.     angle= (((double) i) / n1) * 2.0 * M_PI;
  432.     circle[i].x= cos(angle);
  433.     circle[i].y= sin(angle);
  434.     circle[i].z= 0.;
  435.     base.x = circle[i].x * rb;
  436.     base.y = circle[i].y * rb;
  437.     base.z = 0.;
  438.     top.x = circle[i].x * rt;
  439.     top.y = circle[i].y * rt;
  440.     top.z = h;
  441.     normal[i]= cNormal(circle[i], base, top);
  442.   }
  443.  
  444.   printf("NumMeshes 3\n");
  445.  
  446.   /* Calculate bottom */
  447.   printf("Mesh top_%s%d %d {\n", cone->sid, cone->id, cone->num_disc_polys);
  448.   k = 1;
  449.   for(i=0;i<n1;i++) {
  450.     ii= (i+1) % n1;
  451.     bp->size = 3;
  452.     bp->vertex[0].x = circle[i].x * rb; 
  453.     bp->vertex[0].y = circle[i].y * rb;
  454.     bp->vertex[1].x = circle[ii].x * rb; 
  455.     bp->vertex[1].y = circle[ii].y * rb;
  456.     bp->vertex[0].z = 0.0; bp->vertex[1].z = 0.0;
  457.     bp->vertex[2].x = 0.0; bp->vertex[2].y = 0.0; bp->vertex[2].z = 0.0;
  458.     
  459.     bp->normal[0].x = 0.0; bp->normal[0].y = 0.0; bp->normal[0].z = -1.0;
  460.     bp->normal[1].x = 0.0; bp->normal[1].y = 0.0; bp->normal[1].z = -1.0;
  461.     bp->normal[2].x = 0.0; bp->normal[2].y = 0.0; bp->normal[2].z = -1.0;
  462.  
  463.     print_polygon(bp, k);
  464.     k++; bp++;
  465.   }
  466.   printf("}\n");
  467.  
  468.   /* Calculate top */
  469.   printf("Mesh bot_%s%d %d {\n", cone->sid, cone->id, cone->num_disc_polys);
  470.   k = 1;
  471.   for(i=0;i<n1;i++) {
  472.     ii= (i+1) % n1;
  473.     tp->size = 3;
  474.     tp->vertex[0].x= circle[i].x * rt; tp->vertex[0].y= circle[i].y * rt;
  475.     tp->vertex[1].x= circle[ii].x * rt; tp->vertex[1].y= circle[ii].y * rt;
  476.     tp->vertex[0].z= h; tp->vertex[1].z= h;
  477.     tp->vertex[2].x= 0.0; tp->vertex[2].y= 0.0; tp->vertex[2].z= h;
  478.  
  479.     tp->normal[0].x = 0.0; tp->normal[0].y = 0.0; tp->normal[0].z = 1.0;
  480.     tp->normal[1].x = 0.0; tp->normal[1].y = 0.0; tp->normal[1].z = 1.0;
  481.     tp->normal[2].x = 0.0; tp->normal[2].y = 0.0; tp->normal[2].z = 1.0;
  482.  
  483.     print_polygon(tp, k);
  484.     k++; tp++;
  485.   }
  486.   printf("}\n");
  487.  
  488.   printf("Mesh side_%s%d %d {\n", cone->sid, cone->id, cone->num_side_polys);
  489.   k = 1;
  490.   /* Calculate sides */
  491.   for(i=0;i<n1;i++) {
  492.     ii= (i+1) % n1;
  493.     for(j=0;j<n2;j++) {
  494.       u1= ((double) j)/n2;
  495.       u2= ((double) j+1)/n2;
  496.       s1= rb + u1*(rt-rb);
  497.       s2= rb + u2*(rt-rb);
  498.       
  499.       printf("Patch norm%d 4 {",k);
  500.       if (normal_direction == NORMAL_OUT) {
  501.     printf(" { %g %g %g }", normal[i].x, normal[i].y, normal[i].z);
  502.     printf(" { %g %g %g }", normal[ii].x, normal[ii].y, normal[ii].z);
  503.     printf(" { %g %g %g }", normal[ii].x, normal[ii].y, normal[ii].z);
  504.     printf(" { %g %g %g } }\n", normal[i].x, normal[i].y, normal[i].z);
  505.       } else {
  506.     printf(" { %g %g %g }", -normal[i].x, -normal[i].y, -normal[i].z);
  507.     printf(" { %g %g %g }", -normal[ii].x, -normal[ii].y, -normal[ii].z);
  508.     printf(" { %g %g %g }", -normal[ii].x, -normal[ii].y, -normal[ii].z);
  509.     printf(" { %g %g %g } }\n", -normal[i].x, -normal[i].y, -normal[i].z);
  510.       }
  511.  
  512.       printf("Patch vert%d 4 {",k);     
  513.       printf(" { %g %g %g }", s1*circle[i].x, s1*circle[i].y, u1*h);
  514.       printf(" { %g %g %g }", s1*circle[ii].x, s1*circle[ii].y, u1*h);
  515.       printf(" { %g %g %g }", s2*circle[ii].x, s2*circle[ii].y, u2*h);
  516.       printf(" { %g %g %g } }\n", s2*circle[i].x, s2*circle[i].y, u2*h);
  517.       
  518.       k++;
  519.     }
  520.   }
  521.   printf("}\n");
  522. }
  523.  
  524. /*====================================================================*/
  525. /* Plane */
  526. /*====================================================================*/
  527. void mesh_plane();
  528. void print_plane();
  529. void mesh_plane() {}
  530. void print_plane() {}
  531.  
  532. /*====================================================================*/
  533. /* Meshed Cylinder */
  534. /*====================================================================*/
  535. void mesh_cylinder();
  536. void print_cylinder();
  537.  
  538. /**********************************************************************/
  539. /* Create a polygonally tesselated cylinder                           */
  540. /**********************************************************************/
  541. void mesh_cylinder(cyl, n, id, sid, radius, height)
  542.      MCylinder *cyl;          /* Cylinder to mesh */
  543.      int id;                 /* Cylinder id */
  544.      char *sid;              /* Cylinder string id */
  545.      int n;                  /* number of subdivisions */
  546.      float radius,height;    /* radius and height */
  547. {
  548.   double theta, dtheta, z, dz;
  549.   int vertex_i;
  550.   Polygon *bp, *tp, *sp;
  551.  
  552.   cyl->id = id;
  553.   cyl->sid = sid;
  554.   cyl->r = radius;
  555.   cyl->h = height;
  556.  
  557.   /* Calculate # of side and disc polys and allocate space */
  558.  
  559.   cyl->num_side_polys = 2 * n * n;
  560.   cyl->num_disc_polys = 2 * n;
  561.   if ((sp = cyl->spoly = 
  562.        (Polygon *) malloc(cyl->num_side_polys * sizeof(Polygon))) == NIL) {
  563.     fprintf(stderr,"No more memory left for malloc\n");
  564.     exit(-1);
  565.   }
  566.   if ((tp = cyl->tpoly = 
  567.        (Polygon *) malloc(cyl->num_disc_polys * sizeof(Polygon))) == NIL) {
  568.     fprintf(stderr,"No more memory left for malloc\n");
  569.     exit(-1);
  570.   }
  571.   if ((bp = cyl->bpoly = 
  572.        (Polygon *) malloc(cyl->num_disc_polys * sizeof(Polygon))) == NIL) {
  573.     fprintf(stderr,"No more memory left for malloc\n");
  574.     exit(-1);
  575.   }
  576.   dz = height / (double) n;
  577.   dtheta = M_PI / (double) n;
  578.  
  579.   for (z=(-height/2.0); z < (height/2.0); z=z+dz) {
  580.     for (theta = 0.0; theta < (2 * M_PI); theta += dtheta) {
  581.       
  582.       /* Four vertex points of side patches */
  583.       sp->size = 4;
  584.       sp->vertex[0].z = sp->vertex[1].z = z;
  585.       sp->vertex[0].y = sp->vertex[3].y = radius * cos(theta);
  586.       sp->vertex[0].x = sp->vertex[3].x = radius * sin(theta);
  587.       sp->vertex[1].y = sp->vertex[2].y = radius * cos(theta+dtheta);
  588.       sp->vertex[1].x = sp->vertex[2].x = radius * sin(theta+dtheta);
  589.       sp->vertex[2].z = sp->vertex[3].z = z + dz;
  590.  
  591.       /* Four normals of unit length for side vertices */
  592.       for (vertex_i = 0; vertex_i < 4; vertex_i++) {
  593.     sp->normal[vertex_i].z = 0;
  594.     sp->normal[vertex_i].y = sp->vertex[vertex_i].y / radius;
  595.     sp->normal[vertex_i].x = sp->vertex[vertex_i].x / radius;
  596.       }
  597.  
  598.       /* Top and bottom triangular patches and normals */
  599.       if (z == -1) {
  600.     bp->size = tp->size = 3;
  601.     bp->vertex[0].x = tp->vertex[0].x = sp->vertex[0].x; 
  602.     bp->vertex[0].y = tp->vertex[0].y = sp->vertex[0].y;
  603.     bp->vertex[0].z = -1.; tp->vertex[0].z = 1.;
  604.     bp->vertex[1].x = tp->vertex[1].x = sp->vertex[1].x;
  605.     bp->vertex[1].y = tp->vertex[1].y = sp->vertex[1].y;
  606.     bp->vertex[1].z = -1.; tp->vertex[1].z = 1.;
  607.     bp->vertex[2].x = 0.0; bp->vertex[2].y = 0.0; bp->vertex[2].z = -1.0;
  608.     tp->vertex[2].x = 0.0; tp->vertex[2].y = 0.0; tp->vertex[2].z = 1.0;
  609.     
  610.     bp->normal[0].z = -1.; bp->normal[1].z = -1.; bp->normal[2].z = -1.;
  611.     bp->normal[0].x = 0.; bp->normal[1].x = 0.; bp->normal[2].x = 0.;
  612.     bp->normal[0].y = 0.; bp->normal[1].y = 0.; bp->normal[2].y = 0.;
  613.     tp->normal[0].z = 1.; tp->normal[1].z = 1.; tp->normal[2].z = 1.;
  614.     tp->normal[0].x = 0.; tp->normal[1].x = 0.; tp->normal[2].x = 0.;
  615.     tp->normal[0].y = 0.; tp->normal[1].y = 0.; tp->normal[2].y = 0.;
  616.  
  617.     /* printf("TOP IS"); print_polygon(tp);
  618.     printf("BOT IS"); print_polygon(bp); */
  619.     bp++;
  620.     tp++;
  621.       }
  622.       sp++;
  623.     }
  624.   }
  625. }
  626.  
  627. /**********************************************************************/
  628. /* Print Cylinder normals and points,and colours */
  629. /**********************************************************************/
  630. void print_cylinder(cyl)
  631.      MCylinder *cyl;
  632. {
  633.   int i,j, k;
  634.   Polygon *tp, *bp, *p;
  635.  
  636.   printf("NumMeshes 3\n");
  637.   
  638.   /* Print top */
  639.   k = 1;
  640.   printf("Mesh %s_top%d %d {\n", cyl->sid, k, cyl->num_disc_polys);
  641.   tp = cyl->tpoly;
  642.   for (i=0; i<(cyl->num_disc_polys); i++) {
  643.     printf("Patch norm%d %d {", i+1, tp->size);
  644.     for(j=0;j<(tp->size);j++) {
  645.       if (normal_direction == NORMAL_OUT) 
  646.     printf(" { %g %g %g }", tp->normal[j].x, 
  647.            tp->normal[j].y, tp->normal[j].z);
  648.       else
  649.     printf(" { %g %g %g }", -tp->normal[j].x, 
  650.            -tp->normal[j].y, -tp->normal[j].z);
  651.     }
  652.     printf(" }\n");
  653.  
  654.     printf("Patch vert%d %d {", i+1, tp->size);
  655.     for(j=0;j<(tp->size);j++) 
  656.       printf(" { %g %g %g }", tp->vertex[j].x, tp->vertex[j].y, 
  657.          tp->vertex[j].z);
  658.     printf(" }\n");
  659.     tp++;
  660.   }
  661.  
  662.   /* Print bottom */
  663.   k = 2;
  664.   printf("Mesh %s_bot%d %d {\n", cyl->sid, k, cyl->num_disc_polys);
  665.   bp = cyl->bpoly;
  666.   for (i=0; i<(cyl->num_disc_polys); i++) {
  667.     printf("Patch norm%d %d {", i+1, bp->size);
  668.     for(j=0;j<(bp->size);j++) {
  669.       if (normal_direction == NORMAL_OUT) 
  670.     printf(" { %g %g %g }", bp->normal[j].x, 
  671.            bp->normal[j].y, bp->normal[j].z);
  672.       else
  673.     printf(" { %g %g %g }", -bp->normal[j].x, 
  674.            -bp->normal[j].y, -bp->normal[j].z);
  675.     }
  676.     printf(" }\n");
  677.  
  678.     printf("Patch vert%d %d {", i+1, bp->size);
  679.     for(j=0;j<(bp->size);j++) 
  680.       printf(" { %g %g %g }", bp->vertex[j].x, bp->vertex[j].y, 
  681.          bp->vertex[j].z);
  682.     printf(" }\n");
  683.     bp++;
  684.   }
  685.  
  686.   /* Print sides */
  687.   k = 3;
  688.   printf("Mesh %s_side%d %d {\n", cyl->sid, k, cyl->num_side_polys);
  689.   p = cyl->spoly;
  690.   for (i=0; i<(cyl->num_side_polys); i++) {
  691.     printf("Patch norm%d %d{", i+1, p->size);
  692.     for(j=0;j<(p->size);j++) {
  693.       if (normal_direction == NORMAL_OUT) 
  694.     printf(" { %g %g %g }", p->normal[j].x, 
  695.            p->normal[j].y, p->normal[j].z);
  696.       else
  697.     printf(" { %g %g %g }", p->normal[j].x, 
  698.            p->normal[j].y, p->normal[j].z);
  699.     }
  700.     printf(" }\n");
  701.  
  702.     printf("Patch vert%d %d {", i+1, p->size);
  703.     for(j=0;j<(p->size);j++) 
  704.       printf(" { %g %g %g }", p->vertex[j].x, p->vertex[j].y, 
  705.          p->vertex[j].z);
  706.     printf(" }\n");
  707.     p++;
  708.   }
  709.  
  710.   printf("}\n");
  711. }
  712.  
  713. /**********************************************************************/
  714. /* Tesselate a primitive into some fixed mesh and output it */
  715. /**********************************************************************/
  716. void mesh_primitive(ptype)
  717.      int ptype;
  718. {
  719.   MSphere s;
  720.   MCylinder cy;
  721.   MCube cu;
  722.   MCone co;
  723.   Vector cu_centre;
  724.   int i;
  725.  
  726.   switch (ptype) {
  727.   case MCONE: 
  728.     /* void mesh_cone(cone, rb, rt, h, n1, n2, id, sid) */
  729.     mesh_cone(&co, 1.0, 0.01, 2.0, 16, 16,  5,"MCone");
  730.     break;
  731.   case MCUBE:
  732.     mesh_cube(&cu, 2, 2, 1, "MCube");
  733.     print_cube(&cu);
  734.     for (i=0;i<6;i++) free(cu.faces[i]);
  735.     break;
  736.   case MCYLINDER:
  737.     /* void mesh_cylinder(cyl, n, id, sid, radius, height) */
  738.     mesh_cylinder(&cy, 8, 2,"MCyl", 1.0, 2.0);
  739.     print_cylinder(&cy); 
  740.     free(cy.spoly);
  741.     free(cy.tpoly);
  742.     free(cy.bpoly);
  743.     break;
  744.   case MSPHERE: 
  745.     cu_centre.x = 0.;
  746.     cu_centre.y = 0.;
  747.     cu_centre.z = 0.;
  748.     /* void mesh_sphere(sphere, r, num_sub, centre, id, sid) */
  749.     mesh_sphere(&s, 1.0, 8, cu_centre, 2, "MSphere");
  750.     printf("\n");
  751.     print_sphere(&s);
  752.     free(&s);
  753.     break;
  754.   default: 
  755.     fprintf(stderr, "Somethings wrong. No such primitive exists !\n");
  756.     break;
  757.   }
  758. }
  759.  
  760. /**********************************************************************/
  761. /* main */
  762. /**********************************************************************/
  763. main(argc, argv)
  764.      int argc;
  765.      char *argv[];
  766. {
  767.   int ptype;
  768.  
  769.   if (argc < 3) {
  770.     fprintf(stderr,
  771.         "usage %s [1:CONE | 2:CUBE | 3:CYLINDER | 4:SPHERE]\n",
  772.         argv[0]);
  773.     fprintf(stderr,"\t[0|1 = Normals facing in or out (default)]\n");
  774.     exit(1);
  775.   }
  776.   ptype = atoi(argv[1]);               /* Set type of primitive      */
  777.   normal_direction = atoi(argv[2]);    /* Set direction of normals   */
  778.   switch(ptype) {
  779.     case 1 : ptype = MCONE; break;
  780.     case 2 : ptype = MCUBE; break;
  781.     case 3 : ptype = MCYLINDER; break;
  782.     case 4 : ptype = MSPHERE; break;
  783.     default : break;
  784.     }
  785.   mesh_primitive(ptype);
  786. }
  787.